﻿using Ardalis.GuardClauses;
using Autofac;
using DDD.Common.Const;
using DDD.Core.Vaildate;
using DDD.Domain;
using DDD.Domain.Abstract.DBContext;
using DDD.Domain.Abstract.DBContext.Interceptors;
using DDD.Domain.Abstract.UnitOfWork;
using DDD.Infrastructure.DBContext;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;

namespace DDD.Infrastructure;

[DependsOn(typeof(DomainModule))]
public sealed class InstrastrutureModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        AddDomainDBContext(context.Services, context.Services.GetConfiguration());
        RegisterRepositories(context.Services);
    }

    private void RegisterRepositories(IServiceCollection services)
    {
        var types = System.Reflection.Assembly.GetExecutingAssembly()
            .GetTypes().Where(c => isRepository(c) && !c.IsAbstract && !c.IsInterface);

        if (types != null && types.Any())
        {
            foreach (var type in types)
            {
                var iType = type.GetInterfaces().SingleOrDefault(c => isRepository(c));
                if (iType != null)
                    services.AddScoped(iType, type);
            }
        }

        bool isRepository(Type type)
        {
            return type.Name.EndsWith("Repository", StringComparison.CurrentCultureIgnoreCase);
        }
    }

    private void AddDomainDBContext(IServiceCollection services, IConfiguration configuration)
    {
        services.AddScoped<PublishDomainEventsInterceptor>();
        var dd = configuration.GetConnectionString(AppSettingsConst.ConnectionString.WRITE);
        services.AddDbContext<DDDDomainDbContext>((serviceProvider, option) =>
        {
            string connectionString = Guard.Against.ConfigurationValueNotIsNullOrEmpty(configuration.GetConnectionString(AppSettingsConst.ConnectionString.WRITE)!, AppSettingsConst.ConnectionString.WRITE);

            option.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))
            .AddInterceptors(serviceProvider.GetRequiredService<PublishDomainEventsInterceptor>());
        }, ServiceLifetime.Scoped)
        .AddScoped<DomainDBContext>(provider => provider.GetRequiredService<DDDDomainDbContext>())
        .AddScoped<IUnitOfWork>(provider => provider.GetRequiredService<DDDDomainDbContext>());
    }
}

